import logging

from openlbsserver.lib.base import *
from xml.dom.minidom import parseString

from openlbsserver.lib.decorators import require_valid_xml_post
from openlbsserver.model import meta
from openlbsserver.model import User, UserSession, Device, Location
from datetime import datetime, timedelta
 
log = logging.getLogger(__name__)

# 60 minute expire time
SESSION_EXPIRE = 3600

# update_interval
UPDATE_INTERVAL = 120

class OpenlbsHttpController(BaseController):
    @require_valid_xml_post
    def location(self):
        try:
            
            doc = parseString(request.POST['xml'])

            locUpdateNode = doc.documentElement.firstChild
            
            if locUpdateNode.tagName != 'loc_update':
                return h.abort_xml_error()
            
            secret_key = locUpdateNode.attributes['secret_key'].nodeValue
            
            # validate session
            try:
                device_id = h.validate_session(secret_key)
            except h.SessionExpiredException:
                return h.abort_invalid_session()
            
            
            locations = []
            
            for node in locUpdateNode.childNodes:
                if node.nodeType == node.ELEMENT_NODE and node.tagName == 'location':
                    # add location to the list
                    loc = {}
                    loc['lat'] = node.attributes['lat'].nodeValue
                    loc['lon'] = node.attributes['lon'].nodeValue
                    loc['alt'] = node.attributes['alt'].nodeValue
                    loc['speed'] = node.attributes['speed'].nodeValue
                    loc['heading'] = node.attributes['heading'].nodeValue
                    loc['time'] = int(node.attributes['time'].nodeValue)
                    
                    locations.append(loc)
             
            # add locations
            for loc in locations:
                try:
                    l = Location()
                    l.device_id = device_id
                    l.latitude = float(loc['lat'])
                    l.longitude = float(loc['lon'])
                    l.altitude = float(loc['alt'])
                    l.heading = float(loc['heading'])
                    l.speed = float(loc['speed'])
                    l.date = datetime.utcfromtimestamp(loc['time'])
                    meta.Session.save(l)
                except Exception, msg:
                    print msg
                    pass
                    
            meta.Session.commit()
                
            return h.xml_loc_update_success()
            
        except Exception, msg:
            print msg
            pass
    
        return h.abort_xml_error()


    @require_valid_xml_post
    def auth(self):
        try:
            doc = parseString(request.POST['xml'])
            authNode = doc.documentElement.firstChild
            
            if authNode.tagName != 'auth':
                return h.abort_xml_error()
                
            # get username and password
            username = authNode.attributes['username'].nodeValue
            password = authNode.attributes['password'].nodeValue
            device_uid = authNode.attributes['device'].nodeValue
            
            # authenticate
            try:
                user = meta.Session.query(User).filter_by(username=username).one()
                if not h.auth(user, password):
                    return h.xml_auth_failure('Invalid username or password.')
            except:
                # invalid username
                return h.xml_auth_failure('Invalid username or password.')
            
            # user is authenticated
            
            # make sure user's device exists
            try:
                dev = meta.Session.query(Device).filter_by(user_id=user.id, device_uid=device_uid).one()
            except:
                # doesn't exist, add it
                dev = Device()
                dev.user_id = user.id
                dev.device_uid = device_uid
                meta.Session.save(dev)
                meta.Session.commit()
            
            # set up session
            sess = UserSession()
            sess.device_id = dev.id
            sess.expire_time = datetime.utcnow() + timedelta(seconds=SESSION_EXPIRE)
            sess.key = h.gen_session_key()
            meta.Session.save(sess)
            meta.Session.commit()
            
            return h.xml_auth_success(secret_key=sess.key,update_interval=UPDATE_INTERVAL)
            
            
        except Exception, msg:
            print msg
            pass
            
        return h.abort_xml_error()
